<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <title>线程  &middot; sitename</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1">


<meta name="description" content="线程 description" />

<meta name="keywords" content="one, two, ">


<meta property="og:title" content="线程  &middot; sitename ">
<meta property="og:site_name" content="sitename"/>
<meta property="og:url" content="https://lvzongcheng.gitee.io/java/%E7%BA%BF%E7%A8%8B/" />
<meta property="og:locale" content="en-EN">


<meta property="og:type" content="article" />
<meta property="og:description" content="线程 description"/>
<meta property="og:article:published_time" content="2017-05-13T00:00:00Z" />
<meta property="og:article:modified_time" content="2017-05-13T00:00:00Z" />

  
    
<meta property="og:article:tag" content="one">
    
<meta property="og:article:tag" content="two">
    
  

  

<script type="application/ld+json">
  {
    "@context": "http://schema.org",
    "@type": "Article",
    "headline": "线程",
    "author": {
      "@type": "Person",
      "name": "LvZongCheng"
    },
    "datePublished": "2017-05-13",
    "description": "线程 description",
    "wordCount":  274 
  }
</script>



<link rel="canonical" href="https://lvzongcheng.gitee.io/java/%E7%BA%BF%E7%A8%8B/" />

<link rel="apple-touch-icon-precomposed" sizes="144x144" href="https://lvzongcheng.gitee.io/touch-icon-144-precomposed.png">
<link href="https://lvzongcheng.gitee.io/favicon.png" rel="icon">

<meta name="generator" content="Hugo 0.60.0" />

  <!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->

<link href='https://fonts.googleapis.com/css?family=Merriweather:300%7CRaleway%7COpen+Sans' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/css/font-awesome.min.css">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/highlight/default.css">

  
  
	<script>
	  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

	  ga('create', 'Your Google Analytics tracking code', 'auto');
	  ga('send', 'pageview');

	</script>

</head>
<body>
  <main id="main-wrapper" class="container main_wrapper has-sidebar">
    <header id="main-header" class="container main_header">
  <div class="container brand">
  <div class="container title h1-like">
  <a class="baselink" href="https://lvzongcheng.gitee.io">
  LvZongCheng

</a>

</div>

  
<div class="container topline">
  
  淡定 执著 进取 自律


</div>


</div>

  <nav class="container nav primary no-print">
  

<a class="homelink" href="https://lvzongcheng.gitee.io">home</a>


  
<a href="https://lvzongcheng.gitee.io/framework" title="Show list of Frameworks">Frameworks</a>

<a href="https://lvzongcheng.gitee.io/java" title="Show list of Java">Java</a>

<a href="https://lvzongcheng.gitee.io/linux" title="Show list of Linux">Linux</a>

<a href="https://lvzongcheng.gitee.io/redis" title="Show list of Redis">Redis</a>

<a href="https://lvzongcheng.gitee.io/sql" title="Show list of SQL">SQL</a>

<a href="https://lvzongcheng.gitee.io/Spring" title="Show list of Spring">Spring</a>

<a href="https://lvzongcheng.gitee.io/tools" title="Show list of Tools">Tools</a>

<a href="https://lvzongcheng.gitee.io/webpage" title="Show list of WebPage">WebPage</a>

<a href="https://lvzongcheng.gitee.io/information" title="Show list of information">information</a>

<a href="https://lvzongcheng.gitee.io/network" title="Show list of network">network</a>

<a href="https://lvzongcheng.gitee.io/%E5%BE%AE%E6%9C%8D%E5%8A%A1" title="Show list of 微服务">微服务</a>

<a href="https://lvzongcheng.gitee.io/%E6%80%BB%E7%BB%93" title="Show list of 总结">总结</a>

<a href="https://lvzongcheng.gitee.io/%E6%9C%BA%E5%99%A8%E8%87%AA%E5%8A%A8%E5%8C%96" title="Show list of 机器自动化">机器自动化</a>

<a href="https://lvzongcheng.gitee.io/%E6%B1%87%E7%BC%96" title="Show list of 汇编">汇编</a>

<a href="https://lvzongcheng.gitee.io/%E8%AE%B0%E4%BA%8B%E6%9C%AC" title="Show list of 记事本">记事本</a>


</nav>

<div class="container nav secondary no-print">
  
<a id="contact-link-email" class="contact_link" rel="me" aria-label="Email" href="mailto:Lyc19880405@163.com">
  <span class="fa fa-envelope-square"></span></a>



<a id="contact-link-github" class="contact_link" rel="me" aria-label="Github" href="https://github.com/enten/hugo-boilerplate">
  <span class="fa fa-github-square"></span></a>




 


















</div>


  

</header>


<article id="main-content" class="container main_content single">
  <header class="container hat">
  <h1>线程
</h1>

</header>

  <div class="container content">
  <h3 id="thread">一、创建线程的第一种方式：继承Thread类</h3>
<h6 id="heading">步骤：</h6>
<pre><code>1.  定义类继承Thread  
2.  复写Thread类中的run方法  
  目的：将自定义代码存储在run方法。让线程运行。
  为什么要覆盖run方法:Thread类定义了一个功能，用于存储线程要运行的代码，该存储功能	  
  就是run方法。也就是说Thread类中的run方法，用于存储线程要运行的代码。
3.  调用线程的start方法。  
  该方法两个作用：启动线程，调用run方法。  
4.  使用继承Thread类的方法来创建线程类时，多个线程之间无法共享线程类的实例变量。  
</code></pre>
<h6 id="heading1">语法：</h6>
<p>创建线程</p>
<pre><code>public class FirstThread extends Thread
{
	public void run()
	{
		//当线程类继承Thread 类时，可以直接使用this即可获取当前线程
	}
}
</code></pre><p>启动线程</p>
<pre><code>new FristThread().start();
</code></pre><hr>
<h3 id="runnable">二、创建线程的第二种方法：实现Runnable接口</h3>
<pre><code>Runnable对象仅仅作为Thread对象的target,Runnable实现类里包含的run()方法仅作为线程执行
体。而实际的线程对象依然是Thread实例，只是该Thread线程负责执行其target的run()方法。
</code></pre>
<p>步骤：</p>
<pre><code>1.  定义类实现Runable接口  
2.  覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。  
3.  通过Thread类建立线程对象  
4.  将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。  
    为什么要将Runnable接口的子类对象传递给Thread的构造函数。因为自定义的run方法
    所属的对象是Runable接口的子类对象。所以要让线程去指定对象的run方法。就必须
    明确该run方法所属对象。  
5.  实现Runable接口创建多个线程可以共享线程类的实例变量。  
</code></pre>
<p>创建线程语法：
例：</p>
<pre><code>  public class SecondTread implements Runnable
  {
	
	public void run()
	{
		//当线程类实现Runnable接口时
		//获取当前线程，只能用Thread.currentThread()方法
	}
  }
</code></pre><p>启动线程</p>
<pre><code>SecondThread st=new SecondThread();
new Thread (st,&quot;线程名&quot;).start();
</code></pre><hr>
<h3 id="callablefuture">三、创建线程的第三种方式：实现Callable接口和Future接口</h3>
<pre><code>1.  Callable接口提供了一个call方法可以作为线程执行体，但call方法比run()方法功能更强
  大。*call方法可以有返回值，可以声明抛出异常。
2.  Future接口来代表Callable接口里call()方法的返回值，并为Future接口提供了一个
  FutureTask实现类，该实现类实现了Future接口，并实现了Runnable接口-可以作为Tthread类的target。
</code></pre>
<h6 id="heading2">步骤：</h6>
<pre><code>1.  创建Callable接口的实现类，并实现Call方法，该call()方法将作为线程执行体，且该call()方法有返回值
2.  创建Callable实现类的实例，使用FutureTask类来包装Callable对象，该FutureTask对象封装了该Callable对象的
call()方法的返回值。
3.  使用FutureTask对象作为Thread对象的target创建并启动线程。
4.  调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
</code></pre>
<p>语法：</p>
<pre><code>public ThirdThread implements callable&lt;Integet&gt;
{
	public Integer call()
	{
	
	}
	return ;
}
ThirdThread rt=new ThirdTread();
//使用FutureTask来包装Callable对象
FutureTask&lt;Integer&gt; task=new FutureTask&lt;Integer&gt;(rt);
//启动线程
new Thread(task,&quot;名称&quot;).start()
</code></pre><hr>
<h3 id="heading3">四、三种创建线程对比</h3>
<p>实现Runable接口与实现Callable接口的方式基本相同，只是Callable接口里定义的方法有返回值，可以
声明抛出异常而已。所以实现Runable接口和Callable接口可归为一种方式</p>
<p>实现Runable、Callable接口和Thread类的差别如下
优势:<br>
(1).可以继承其他类<br>
(2).多个线程可以共享同一个target对象，适合多个相同线程来处理同一份资源的情况，<br>
劣势:<br>
编程稍稍复杂，如需要访问当前线程，必须使用Thread.currentThread()方法。</p>
<p>继承Thread类的方式创建多线程</p>
<p>优势:<br>
编写简单，如需访问当前线程无需使用Thread.currentThread()方法，直接使用this即获得当前<br>
线程<br>
劣势:<br>
不能再继承其他类</p>
<hr>
<h3 id="heading4">五、线程声明周期</h3>
<h6 id="newrunnablerunningblockeddead5">新建（New）、就绪（Runnable）、运行（Running）、阻塞（Blocked）和死亡（Dead）5种状态:</h6>
<ul>
<li>调用start()进入就绪状态</li>
<li>join()等待另一个线程完成。</li>
<li>sleep()线程睡眠，睡眠时间类不会获得执行机会。</li>
<li>yield()线程让步，不会阻塞线程，只是将线程转入就绪状态。只有优先级与当前线程相同，或者优先级
比当前线程更高的处于就绪状态的线程才会获得执行机会。</li>
<li>setPriority()、getpriority()设置和返回线程优先级，参数1-10之间也可以用以下三个静态常量</li>
</ul>
<ul>
<li>MAX_PRIORITY:值是10</li>
<li>MIN_PRIORITY:值是1</li>
<li>NORM_PRIORITY:值是5</li>
</ul>
<h6 id="sleppyield">slepp()与yield()的区别</h6>
<ol>
<li>sleep()暂停线程，给其他线程执行机会，不会理会其他线程优先级。</li>
<li>sleep()将线程转入阻塞状态，阻塞时间到后才会转入就绪状态，yield将线程转入就绪状态。</li>
<li>sleep()方法声明抛出InterruptedException异常，yield没有声明抛出任何异常。</li>
<li>sleep()方法比yield()有更好的可移植性，并发线程不建议用yield</li>
</ol>
<h6 id="heading5">后台线程</h6>
<p>setDaemon(true) 将指定线程设定为守护线程（后台线程）。
如果要将某个线程设置为后台线程，必须在该线程启动之前设置。也就是setDaemon(true)必须在
start()之前调用	
isDaemon()判断指定线程是否为守护线程（后台线程）。
后台线程特征：所以前台线程都死亡，后台线程会自动死亡。
后台线程是为其他线程服务。</p>
<hr>
<h3 id="heading6">六、同步的前提：</h3>
<ol>
<li>必须要两个或两个以上的线程。</li>
<li>必须是多个线程使用同一个锁。</li>
</ol>
<p>同步代码语法</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>同步方法
就是用synchronized来修饰方法
synchronized可以修饰方法代码块。但不可以修饰构造器、属性等</p>
<p>StringBuilder:用于单线程环境下，保证较好的性能。
StringBuffer:用于多线程，保证多线程安全。</p>
<p>释放同步监视器的锁定：
任何线程进入同步代码块、同步方法之前，必须先获得对同步监视器的锁定。</p>
<h6 id="1">1.释放同步监视器的情况；</h6>
<ul>
<li>当前线程的同步方法、同步代码块执行结束，当前线程即释放同步监视器</li>
<li>当前线程在同步代码块、同步方法中遇到break、return终止了该代码块、
该方法的继续执行，当前线程将会释放同步监视器。</li>
<li>当前线程在同步代码、同步方法中出现了未处理的Error或Exception,导致
该代码块、该方法异常结束时，当前线程将会释放同步监视器。</li>
<li>当前线程执行同步代码块或同步方法，程序执行了同步监视器对象的wait()
方法，则当前线程暂停，并释放同步监视器。</li>
</ul>
<h6 id="2">2.线程不会释放同步监视器的情况：</h6>
<ul>
<li>线程执行同步代码块或方法时，程序调用Thread.sleep()、Thread.yiele()
方法来暂停当前线程的执行，当前线程不会释放同步监视器。</li>
<li>线程执行同步代码块时，其他线程调用了该线程的supend()方法将该线程挂起
来该线程不会释放同步监视器。</li>
</ul>
<h6 id="lock">同步锁（Lock）</h6>
<p>Lock是Java提供的一种功能更强大的线程同步机制——通过显示定义同步锁。
Lock是控制多个线程对共享资源进行访问的工具。</p>
<h6 id="lock--readwritelock">根接口Lock 和 ReadWriteLock</h6>
<ul>
<li>Lock的实现类ReentrantLock（可重入锁），即可重入性，也就是一个线程可以对已被
加锁的ReentrantLock锁再次加锁。</li>
<li>ReadWriteLock（读写锁）的实现类 ReentrantReadWriteLock实现类。</li>
</ul>
<ul>
<li>ReadWriteLock锁允许对共享资源并发访问。</li>
</ul>
<p>使用ReentrantLock锁的代码格式：</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>线程在每次调用lock()锁后，必须显示调用unlock()来释放锁。
一段被锁保护的代码可以调用另一个被相同锁保护的方法。</p>
<p>死锁
整个程序即不会发生任何异常，也不会给出任何提示，只是所有线程处于阻塞状态，无法继续。</p>
<hr>
<h3 id="heading7">七、线程间通信</h3>
<h4 id="1--synchronized">1.  对于使用synchronized同步方法</h4>
<p>默认实例（this)就是同步监视器，所以可以直接调用这三个方法。
对于使用synchronized同步代码块,同步监视器就是后括号里的对象，所以必须使用该对象调用
这三个方法
Object类提供了wait()、notify()、notifyAll()三个方法，不属于Thread类</p>
<pre><code>(1) wait()让当前线程等待，直到其他线程调用该同步监视器的notify()方法或notifyAll()方法来唤醒线程
    |——有无参和带参两种
(2) notify()唤醒在此同步监视器上等待的多个线程中任意一个线程（是使用wait()锁定的）
(3) notifyAll()唤醒在此同步监视器上等待的所有线程	
</code></pre>
<h4 id="2--condition">2.  使用Condition控制线程通信</h4>
<ol>
<li>如果程序不使用synchronized关键字来保证同步，而是直接使用Lock对象来保证同步，则系统中不存在隐式的同步
监视器，也就不能使用wait()、notify()、notifyAll()方法进行线程间通信。</li>
<li>当使用Lock对象来保证同步时，就需要使用Condition来保持协调，让已经得到Lock对象确无法继续执行的线程释放
Lock对象，Condition对象也可以唤醒其他处于等待的线程。
Condition将同步监视器方法（wait()、notify()、notifyAll()）分解成不同对象，以便这些对象与Lock组合使用，为
每个对象提供多个等待集。 Lock替代同步方法或同步代码块，Conditin替代了同步监视器的功能。</li>
<li>Condition实例被绑定在Lock对象上，调用Lock对象的newCondition()方法才能获得特定Lock实例的Condition实例。</li>
</ol>
<h6 id="condition">Condition实例提供如下方法：</h6>
<pre><code>(1) await():类似隐式监视器的wait()方法，让当前线程等待。其他线程调用该Condition的signal()或singalAll()
    方法来唤醒该线程。await()方法还有其他变体完成更丰富的等待操作。（详看帮助文档）
(2) sinal():唤醒在此Lock对象上等待的单个线程，有多个时选择任意一个。只有线程放弃锁定(用await放弃锁定)，
    才可以执行被唤醒的线程。
(3) signalAll():唤醒在此对Lock对象上等待的所有线程。只有线程放弃锁定(用await放弃锁定)，才可以执行被唤
    醒的线程。
</code></pre>
<hr>
<h3 id="blockingqueue">八、使用阻塞队列（BlockingQueue接口）控制线程通信</h3>
<h4 id="1blockingqueuequeue">1.BlockingQueue接口是Queue的子接口。</h4>
<p>BlockingQueue特性：
向BlockingQueue放入元素时，如果该队列已满，则该线程被阻塞。
向BlockingQueue取出元素时，如果该队列已空，则该线程被阻塞。</p>
<h4 id="2blockingqueue">2.BlockingQueue实现方法有：</h4>
<pre><code>ArrayBlockingQeue:基于数组
LinkedBlockingQeue:基于链表
</code></pre>
<h6 id="priorityblockingqeue">PriorityBlockingQeue:</h6>
<ul>
<li>remove()、poll()、take()取出元素是取出队列中最小的。</li>
<li>可以更具元素大小进行排序（要实现Comparable接口）</li>
<li>使用Comparator进行定制排序
SynchronousQueue:对该队列的存、取操作必须交替进行。
DelayQueue:要求集合元素都实现Delay接口，根据元素的getDalay()方法的返回值进行排序。</li>
</ul>
<hr>
<h3 id="heading8">九、线程组和异常</h3>
<p>Java使用ThreadGroup来表示线程组，它可以对一批线程进行分类管理，Java允许程序直接对线程
组进行控制。用户创建的所有线程都属于指定线程组，如果没有显示指定线程组，则属于默认线程
组。
Thread 类提供构造器来设置新创建的线程属于哪个线程组。
例：Thread(ThreadGroup group,Runnable target):以garget的run()方法作为线程执行
体创建新线程。
(更多请看帮助文档)</p>
<hr>
<h3 id="heading9">十、线程池</h3>
<h6 id="executors">使用Executors工厂类来产生线程池，包含以下几个静态方法来创建线程池。</h6>
<pre><code>(1) .  newCachedThreadPool():创建具有缓存功能的线程池，这些线程将会被缓存在线程池中。
(2) newFixedThreadPool(int nThreads):创建一个可重用的、具有固定线程数的线程池。
(3) newSingleThreadExecutor():创建一个只有单线程池，相当于调用newFixedThreadPool
    方法时传入参数为1.
(4) newScheduledThreadPool(int corePoolSize):创建只有一个线程的线程池，他可以在指
    定延迟后执行线程任务。corePoolSize指池中所保存的线程数，即使线程是空闲的
    也被保存在线程池内。
(5) newSingleThreadScheduledExecutor():创建只有一个线程的线程池，他可以在指定延迟
    后执行线程任务。
</code></pre>
<p>Java7提供ForkJoinPool来支持将一个任务拆分成多个“小任务”并行计算，再把多个小任务的结果
合并成总的计算结果，ForkJoinPool是ExecutorService的实现类。是一种特殊的线程池。
这是为了适应多核CPU的发展，充分利用多核CPU的性能优势。</p>

</div>


  
</article>
      <footer id="main-footer" class="container main_footer">
  

  <div class="container nav foot no-print">
  
<a href="https://lvzongcheng.gitee.io/license">license</a>


  <a class="toplink" href="#">back to top</a>

</div>

  <div class="container credits">
  
<div class="container footline">
  
  code with <!-- raw HTML omitted --><!-- raw HTML omitted -->


</div>


  
<div class="container copyright">
  
  (c) 2015 yourname.


</div>


</div>

</footer>

    </main>
    
<script type="text/javascript">
  (function() {
    
    
    if (window.location.hostname == "localhost")
      return;
    var dsq = document.createElement('script'); dsq.async = true; dsq.type = 'text/javascript';
    dsq.src = '//your_disqus_shortname.disqus.com/count.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
  })();
</script>



<script src="/js/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>



    
  </body>
</html>

